#!/bin/bash
dir=/opt/NONMEM/nm73
f=ifort
o=' -fp-model strict -Gs -nologo -nbs -w '
opstat=' -static '
lib=

# 2014-02-28 Tim Bergsma.  Modified for use with NMQual.
# We need to accept a compile/execute option, and we need
# to strip it off the arg list before  the regular code sees it.
if [ $1 != "c" ] && [ $1 != "e" ] && [ $1 != "ce" ]  
then 
  mode='ce'
else 
  	mode=$1
  	shift
fi
compile=0
execute=0

if [ $mode == "c" ];  then compile=1; fi
if [ $mode == "ce" ]; then compile=1; fi 
if [ $mode == "e" ];  then execute=1; fi
if [ $mode == "ce" ]; then execute=1; fi

r=$dir/resource/resource.a
lfile=$dir/license/nonmem.lic
compile_type=0
if [ $f == "ifort" ]; then compile_type=0 ; fi
if [ $f != "ifort" ]; then compile_type=1 ; fi
if [ $f != "ifort" ] &&  [ `uname` == "Darwin" ] ; then compile_type=2 ; fi
ndir=$dir/nm
n="$ndir/NONMEM.o $ndir/nonmem.a"
exitcode=0
export exitcode
# for user library
u=
if [ -z $1 ] || [ -z $2  ]
then
	echo Usage:
	echo "nmfe73 infile outfile [-background] [-PARAFILE=file.pnm] [-licfile=filename]"
	echo "  [-prsame] [-prdefault] [-prcompile] [-tprdefault] [-trskip] "
	echo "  [-maxlim=0, 1, 2, or 3]  [-locfile=file] "
	echo "  [-rundir=dirname]"
	echo "  [-runpdir=dirname] [-nmexec=filename] [-xmloff]"
	echo "Default:"
	echo "nmfe73 infile outfile"
	echo "  -licfile=$lfile"
	echo "  -prsame (if possible; else -prcompile)"
	echo "  -rundir=`pwd`"
	echo "  -runpdir=temp_dir -nmexec=nonmem"
  	exitcode=100
  	exit $exitcode
fi

shopt -s nocasematch
if [[ $1 == $2 ]]
then
	echo output file name/extension should not be same as input file name/extension
  	exitcode=101
  	exit $exitcode
fi
shopt -u nocasematch

$dir/util/OPTION_CHECK $*
status=$?
if [ ! $status -eq 0 ] ; then exitcode=1002;   exit $exitcode ; fi
while read file_name ; do rundir=${file_name} ;  done < rundir.set
if [ $rundir == "0" ] ; then rundir=$PWD ; fi
while read file_name ; do runpdir=${file_name} ;  done < runpdir.set
if [ $runpdir == "0" ] ; then runpdir=temp_dir ; fi
while read file_name ; do nmexec=${file_name} ;  done < nmexec.set
if [ $nmexec == "0" ] ; then nmexec=nonmem ;fi
while read file_name ; do trskip=${file_name} ;  done < trskip.set
while read file_name ; do prsame=${file_name} ;  done < prsame.set
while read file_name ; do prcompile=${file_name} ;  done < prcompile.set
while read file_name ; do prdefault=${file_name} ;  done < prdefault.set
while read file_name ; do tprdefault=${file_name} ;  done < tprdefault.set
while read file_name ; do maxlim=${file_name} ;  done < maxlim.set
while read file_name ; do licfile=${file_name} ;  done < licfile.set
if [ $licfile != "0" ] ; then lfile=$licfile ; fi
while read file_name ; do locfile=${file_name} ;  done < locfile.set
if [ $locfile == "0" ] ; then locfile=nmloc ; fi
rundir=${rundir/"~"/$HOME}
nmexec=${nmexec/"~"/$HOME}
runpdir=${runpdir/"~"/$HOME}
lfile=${lfile/"~"/$HOME}

if [ $rundir != $PWD ]
then 
	if [ ! -e $rundir ]
	then
		echo Directory $rundir does not exist.  Make sure directory exists with all necessary input files.
		exitcode=103
		exit $exitcode
	fi
	rm  background.set
	rm  licfile.set
	rm  locfile.set
	rm  nmexec.set
	rm  parafile.set
	rm  prcompile.set
	rm  prdefault.set
	rm  maxlim.set
	rm  tprdefault.set
	rm  prsame.set
	rm  rundir.set
	rm  runpdir.set
	rm  trskip.set
	rm  worker.set
	rm  xmloff.set
	echo changing directory to $rundir
	pushd $rundir
	status=$?
	if [ ! $status -eq 0 ] ; then exitcode=104;   exit $exitcode ; fi
	# rerun OPTION_CHECK, make sure appropriate files exist in this new run directory.
	$dir/util/OPTION_CHECK $* -norundir
	status=$?
	if [ ! $status -eq 0 ] ; then exitcode=105;   exit $exitcode ; fi
fi

if [ $compile -eq 1 ]  # TB
then
	echo  >newline
	date >$2
  $f --version >>$2
	if [ ! -e $1 ]
	then
		echo File $1 does not exist.
		cat $2 newline >trash.tmp
		cat trash.tmp >$2 
		echo $1 does not exist. >> $2
		exitcode=106
		exit $exitcode
	fi

	if [ $trskip != "1" ]
	then
		echo Starting NMTRAN
		if [ -e FSUBS ]       ; then rm FSUBS       ; fi
		if [ -e FSUBS2 ]      ; then rm FSUBS2      ; fi
		if [ -e FSUBS.f90 ]   ; then rm FSUBS.f90   ; fi
		if [ -e FSUBS_MU.F90 ]; then rm FSUBS_MU.F90; fi
		if [ -e FLIB ]        ; then rm FLIB        ; fi
		if [ -e FREPORT ]     ; then rm FREPORT     ; fi
		if [ -e LINK.LNK ]    ; then rm LINK.LNK    ; fi
		if [ -e ${f}.txt ]    ; then rm ${f}.txt    ; fi
		if [ -e $nmexec ]     ; then rm $nmexec     ; fi
		if [ -e FMSG ]        ; then rm FMSG        ; fi
		if [ $tprdefault == "1" ] ; then prdefault=1 ; fi
		$dir/tr/NMTRAN.exe $prdefault $tprdefault $maxlim < $1 >& FMSG
		status=$?
		if [  $status -eq 2 ] ; then prdefault=0 ; fi
		if [ $prdefault == "1" ] 
		then 
			prcompile=0
			prsame=0
		fi
		if [ -e FSUBS ]
		then
			cp FSUBS FSUBS.f90 
			cat FSUBS.f90 >trash.tmp
		fi
		cat FMSG
	fi

	if [ $prdefault != "1" ]
	then
		tempdir=$runpdir
		pdir=$tempdir
		rdir=$tempdir
	else
		tempdir=$dir/resource
		pdir=$dir/pr
		rdir=$dir/resource
	fi

	s=
	cat $2 $1 newline >trash.tmp
	cat trash.tmp>$2 
	echo NM-TRAN MESSAGES >>$2
	cat FMSG newline >>$2
	if [ ! -e FREPORT ]
	then
		exitcode=107
		if [ $trskip == "1" ]
		then
			echo MESSAGES FROM PREVIOUS NMTRAN RUN:
			cat FMSG 
			exitcode=108
		fi
		exit $exitcode
	fi
	$dir/util/NMLINK7.exe none "/" ".o"
	cp LINK.LNK LINKC.LNK
	$dir/util/NMLINK7.exe $pdir "/" ".o"
	if [ -e FSUBS ]
	then
		cp FSUBS FSUBS.f90
		s=FSUBS.f90
	fi

	#compile

	compilerpath=
	mpibinpath=
	mpilibpath=
	mpilibname=
	if [ ! -e $locfile ]; then locfile=$dir/nmloc; fi
	if [ -e $locfile   ] 
	then 
		source $locfile
		if [ $compilerpath != "" ]
		then
			if [ $old_path != "" ]; then PATH=$old_path; fi
			old_path=$PATH
			PATH=${compilerpath}:$PATH
			echo Pathlist information for compiler and MPI systems are located in nmpathlist.txt
			echo The pathlist $compilerpath obtained from file $locfile is placed at the head of PATH >nmpathlist.txt
			echo The $f compiler at one of those locations will be used if it exists. >>nmpathlist.txt
			echo If this is not what you want, then modify the file $locfile accordingly. >>nmpathlist.txt
			echo
		fi
	fi

	if [ $prdefault != "1" ] && [ $prsame != "1" ]
	then
		if [ -e nmprd4p.mod ] ; then rm nmprd4p.mod ; fi
		if [ -e compile.lnk ] ; then rm compile.lnk ; fi
		$dir/util/COMPILE7.exe $dir/pr "/" ".o"
		predskip=1
		# force a pred recompile if -prcompile is given by user
		if [ $prcompile == "1" ]  ;  then predskip=0 ; fi
		if [ $predskip == "1" ]
		then
			if [ ! -e $tempdir ] ; then predskip=0 ;  fi
		fi
		# The following lines test if all pred components in $tempdir are correct for present run.  If not, must 
		# do predpp recompiles.
		if [ $predskip == "1" ]
		then
			if [ ! -e $tempdir/PRSIZES.o ] || [ ! -e $tempdir/PRSIZES.f90 ] || [ ! -e $tempdir/compile.lnk ]  || [ ! -e $tempdir/PRGLOBALP.o ] || [ ! -e $tempdir/PRPNM.o ] || [ ! -e $tempdir/MUMODEL.o ]  || [ ! -e $tempdir/LINK.LNK ] ;  then predskip=0 ; fi
		fi
		if [ $predskip == "1" ]
		then
			cmp -s PRSIZES.f90 $tempdir/PRSIZES.f90
			status=$?
			if [ ! $status -eq 0 ] ;  then predskip=0 ; fi
			cmp -s compile.lnk $tempdir/compile.lnk
			status=$?
			if [ ! $status -eq 0 ] ; then predskip=0 ; fi
			cmp -s LINK.LNK $tempdir/LINK.LNK
			status=$?
			if [ ! $status -eq 0 ] ; then predskip=0 ; fi
		fi

		# uncomment following line if you always want recompile of pred routines except when user specifies -prsame
		# predskip=0

		#lpreddo
		if [ $predskip == "0" ]
		then
			echo Recompiling certain components
			if [ -e $tempdir ]; then rm -rf $tempdir/ ; fi
			mkdir $tempdir
			cp LINK.LNK $tempdir/
			cp LINKC.LNK $tempdir/
			cp compile.lnk $tempdir/
			cp PRSIZES.f90 $tempdir/
			nmcdir=$PWD
			cd $tempdir
			cp $dir/resource/PRGLOBALP.f90 .
			cp $dir/resource/*.mod .
			cp $dir/resource/TOTAL.INC .
			cp $dir/pr/MUMODEL.f90 .
			cp $dir/pr/PRPNM.f90 .
			$f -c $o PRSIZES.f90
			$f -c $o PRGLOBALP.f90
			$f -c $o MUMODEL.f90 &
			$f -c $o PRPNM.f90 &
			while read file_name1
			do
			cp $dir/pr/$file_name1 .
			done < LINKC.LNK
			while read file_name2
			do
			cp ${file_name2}.f90 .
			done < compile.lnk
			while read file_name3
			do
			$f -c $o ${file_name3}.f90 &
			done < compile.lnk
			wait
			#  cp *.o ../
			cd $nmcdir
		fi
	fi # prdefault/prsame
fi # if compile=1

#lpredskip
# if [ -e nmmpi.sh ] ; then rm nmmpi.sh ; fi  ## TB removed before creation in compile phase below
# NONMEM_MPI.exe is called just to check what transfer type is to be used, and make sure .pnm file is syntactically okay.
if [ -e PARALLEL.pnm ] ; then rm PARALLEL.pnm ; fi
$dir/util/NONMEM_MPI.exe $1 -licfile=$lfile -check -linux $* -nmexec=$nmexec

status=$?
if [ $status -eq 1 ] # parallel
then
	if [ $compile -eq 1 ] #TB 
	then # TB
		# lmpi
		export dir f mpibinpath mpilibpath mpilibname
		$dir/util/getmpi linux >>nmpathlist.txt
		source mpiloc
		echo mpi library file to be used is $mpilib >>nmpathlist.txt
		old_path2=$PATH
		PATH=${mpibinpath}:${PATH}

		MPICH_F90=$f
		export MPICH_F90
		if [ -e $nmexec ] ; then rm $nmexec ; fi

		echo Building NONMEM Executable
		# IFORT
		if [ $compile_type == "0" ]
		then
			mpif90 $o -o $nmexec $s $dir/mpi/mpi_lini/PNM_MPI.o -I$tempdir -I$dir/resource `cat LINK.LNK` $dir/resource/PRGLOBAL.o $rdir/PRGLOBALP.o $pdir/MUMODEL.o $dir/util/PARALLEL.o $pdir/PRPNM.o $n $mpilib $r > ${f}.txt
		fi
		# not IFORT, not Darwin
		if [ $compile_type == "1" ]
		then
			mpif90 $o -o $nmexec $s $dir/mpi/mpi_ling/PNM_MPI.o -I$tempdir -I$dir/resource `cat LINK.LNK` $dir/resource/PRGLOBAL.o $rdir/PRGLOBALP.o $pdir/MUMODEL.o $dir/util/PARALLEL.o $pdir/PRPNM.o $n $mpilib -lrt $u $r > ${f}.txt
		fi
		# not IFORT, Darwin
		if [ $compile_type == "2" ]
		then
			mpif90 $o -o $nmexec $s $dir/mpi/mpi_ling/PNM_MPI.o -I$tempdir -I$dir/resource `cat LINK.LNK` $dir/resource/PRGLOBAL.o $rdir/PRGLOBALP.o $pdir/MUMODEL.o $dir/util/PARALLEL.o $pdir/PRPNM.o $n $mpilib $u $r > ${f}.txt
		fi

		if [ ! -e $nmexec ]
		then
			echo No nonmem execution ... parallel executable is missing
			exitcode=111
			exit $exitcode
		fi
		# Now NONMEM_MPI.exe is called again, to create nmmpi.bat file for mpi transfer type.
		# NONMEM_MPI.exe has to be called again for mpi methods, because it copies nonmem to worker directories.
		# This could not be done until nonmem was created.
		# rm -rf $tempdir/
		# rm *.o
		if [ -e nmmpi.sh ] ; then rm nmmpi.sh ; fi
		$dir/util/NONMEM_MPI.exe $1 -licfile=$lfile -linux $* -nmexec=$nmexec
		status2=$?
		if [ $status2 -eq 2 ]
		then
			echo No nonmem execution ... NONMEM_MPI.exe error 2
			exitcode=112
			exit $exitcode
		fi
	fi #TB compile parallel
	if [ $execute -eq 1 ] #TB
	then #TB
		if [ -e nmmpi.sh ]
		then
			chmod +x nmmpi.sh
			echo Starting MPI version of nonmem execution ...
			./nmmpi.sh $1 -licfile=$lfile $* -nmexec=$nmexec
			status=$?
			if [ $status -gt 1 ] ; then exitcode=115 ; fi
		else
			echo No nonmem execution ... parallelization script missing
			exitcode=113
			exit $exitcode
		fi
	fi #TB execute parallel
elif [ $status -eq 0 ] # serial
then
	if [ $compile -eq 1 ] #TB compile serial
	then #TB
		# lfile
		echo Building NONMEM Executable
		# nonmem is invoked with the control stream file name as an argument.  This allows raw output files
		# to have by default the control stream root name.
		# Console directed output can be redirected to an output file by adding a pipe to the command: >myconsole.txt
		$f $o $opstat -o $nmexec  $s $ndir/PNM_MPID.o  -I$tempdir -I$dir/resource `cat LINK.LNK`  $dir/resource/PRGLOBAL.o $rdir/PRGLOBALP.o $pdir/MUMODEL.o $dir/util/PARALLEL.o $pdir/PRPNM.o $n $u $r > ${f}.txt
		if [ ! -e $nmexec ]
		then
			echo No nonmem execution ... serial executable is missing
			exitcode=110
			exit $exitcode
		fi
		# rm -rf $tempdir/
		# rm *.o
	fi #TB compile serial
	if [ $execute -eq 1 ] #TB
	then #TB
		echo Starting nonmem execution ...
		./$nmexec $1 -licfile=$lfile $* -nmexec=$nmexec
		status=$?
		if [ ! $status -eq 0 ] ; then exitcode=114 ; fi
	fi #TB
else
	echo No nonmem execution ... unknown status for NONMEM_MPI.exe
	exitcode=109
	exit $exitcode
fi

if [ $execute -eq 1 ]
then
	cat $2 OUTPUT >trash.tmp
	mv trash.tmp $2
	echo Stop Time: >>$2
	date >>$2
	rm OUTPUT
fi
exit $exitcode
